package main

import (
	"fmt"
	"reflect"
)

func main() {
	reflectTest01(100)
	reflectTest02(Student{Name: "tom", Age: 18})
	reflectTest02(Monster{Name: "jack", Age: 20})
	differentBetweenTypeAndKind()
	reflectTest03()
}

// reflectTest01
//
//	@Description: 通过反射获取 type kind 值
//	@param in
func reflectTest01(in interface{}) {
	typeOf := reflect.TypeOf(in)
	fmt.Println("typeOf=", typeOf)             //int
	fmt.Println("typeOf.Name=", typeOf.Name()) //int
	fmt.Println("typeOf.Kind=", typeOf.Kind()) //int

	valueOf := reflect.ValueOf(in)
	fmt.Printf("%v %T \n", valueOf, valueOf) //100 reflect.Value
	//num := 100+valueOf  //Invalid operation: 100+valueOf (mismatched types untyped int and Value)
	num := 100 + valueOf.Int() //num= 200
	fmt.Println("num=", num)

	//valueOf - > interface{}
	inter := valueOf.Interface()
	//类型断言
	v, ok := inter.(int)
	if ok {
		fmt.Printf("assert -v=%d -t=%T \n", v, v)
		//assert -v=100 -t=int
	}

	fmt.Println()
}

func reflectTest02(in interface{}) {
	typeOf := reflect.TypeOf(in)
	fmt.Println("typeOf=", typeOf)             //Student/Monster
	fmt.Println("typeOf.Name=", typeOf.Name()) //Student/Monster
	fmt.Println("typeOf.Kind=", typeOf.Kind()) //struct

	valueOf := reflect.ValueOf(in)
	inter := valueOf.Interface()
	fmt.Printf("%v %T \n", inter, inter) //{tom 18} main.Student
	//此时无法获取student的field，method
	switch inter.(type) {
	case Monster:
		fmt.Println("monster=", inter.(Monster))
	case Student:
		fmt.Println("student=", inter.(Student))
	default:
		fmt.Println("-------")

	}

}

func differentBetweenTypeAndKind() {
	var num = 10
	typeOf := reflect.TypeOf(num)                // 类型
	fmt.Printf("type: %T %v \n", typeOf, typeOf) //type: *reflect.rtype int
	kind := reflect.ValueOf(num).Kind()          //类别，返回的是一个常量,大地类别
	fmt.Printf("kind: %T %v \n", kind, kind)     //kind: reflect.Kind int
	fmt.Println("--------------------------")
	stu := Student{Name: "tom", Age: 18}
	of := reflect.TypeOf(stu)
	fmt.Printf("type: %T %v \n", of, of) //type: *reflect.rtype main.Student
	k := of.Kind()
	fmt.Printf("kind: %T %v \n", k, k) //kind: reflect.Kind struct
}

// reflectTest03
//
//	@Description: 使用反射修改变量 ,必须传入地址
func reflectTest03() {
	var str = "tom"
	of := reflect.ValueOf(&str)
	//of.Elem() 返回of指针返回的具体的值，然后才能进行设置值
	of.Elem().SetString("jack")
	fmt.Println(str)

	var num = 100
	valueOf := reflect.ValueOf(&num)
	valueOf.Elem().SetInt(101)
	fmt.Println(num)

}

type Student struct {
	Name string
	Age  int
}
type Monster struct {
	Name string
	Age  int
}
